(Rust) Cofactor checkings
libra ref
Cofactor signature checking
mul_by_cofactor
rand時、署名時など
生成する点がprime orderである保証はない
不要にcofactorをかけると8bit security犠牲にする
code:1.rs
/// This guarantees the point is in the prime order subgroup
pub fn mul_by_cofactor(&self, params: &E::Params) -> Point<E, PrimeOrder>
{
let tmp = self.double(params)
.double(params)
.double(params);
convert_subgroup(&tmp)
}
as_prime_order
read時(別途、zero pointバリデーションは必要)
読み取るbytesはある点をバイトキャストしていることが前提なので。
non-prime orderの場合はError
8bit mulしないのでsecurity bitは犠牲にしない
code:1.rs
/// Attempts to cast this as a prime order element, failing if it's
/// not in the prime order subgroup.
pub fn as_prime_order(&self, params: &E::Params) -> Option<Point<E, PrimeOrder>> {
if self.mul(E::Fs::char(), params) == Point::zero() {
Some(convert_subgroup(self))
} else {
None
}
}
任意のバイト列からreadしたpointはunknownなので、as_prime_orderでprime化。
code:1.rs
pub fn read<R: Read>(mut reader: R, params: &E::Params) -> io::Result<Self> {
let ak = edwards::Point::<E, Unknown>::read(&mut reader, params)?;
let ak = match ak.as_prime_order(params) {
Some(p) => p,
None => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"ak not in prime-order subgroup",
));
}
};
if ak == edwards::Point::zero() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"ak not of prime order",
));
}
}
pointのrand生成はprime orderの保障がない
code:1.rs
// Create random viewing key
let vk = ViewingKey::<Bls12> {
ak: edwards::Point::rand(&mut rng, ¶ms).mul_by_cofactor(¶ms),
nk: edwards::Point::rand(&mut rng, ¶ms).mul_by_cofactor(¶ms),
};
redjubjub public key はデフォルトでprime orderではない。
code:1.rs
pub struct PublicKey<E: JubjubEngine>(pub Point<E, Unknown>);
code:1.rs
// 0 = h_G(-S . P_G + R + c . vk)
self.0.mul(c, params).add(&r, params).add(
¶ms.generator(p_g).mul(s, params).negate().into(),
params
).mul_by_cofactor(params).eq(&Point::zero())
code:1.rs
fn cofactor_check() {
let rng = &mut XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let params = &JubjubBls12::new();
let zero = edwards::Point::zero();
let p_g = FixedGenerators::SpendingKeyGenerator;
// Get a point of order 8
let p8 = loop {
let r = edwards::Point::<Bls12, _>::rand(rng, params).mul(Fs::char(), params);
let r2 = r.double(params);
let r4 = r2.double(params);
let r8 = r4.double(params);
if r2 != zero && r4 != zero && r8 == zero {
break r;
}
};
ask -> akなどはgenerator pointがすでにprime orderであることが保障されているのでscalar mul時にcofactor mulする必要はない。
code:1.rs
/// Returns a fixed generator.
fn generator(&self, base: FixedGenerators) -> &edwards::Point<E, PrimeOrder>;
Scalar field
https://gyazo.com/bda93fb634ee1f8077010b1fb8583c7e
Calculate circuit costs of prime group operations (Ristretto or ctEdwards-subgroup)
Improve subgroup enforcements
Montgomery curves and their arithmetic
Faster variable-base scalar multiplication in zk-SNARK circuits
Understand how to optimize a circuit implementation of Groth16 verification
refs
key exchange時にボブがlow-orderなbGを渡すと、shared keyのabGからボブは8 iterationsだけでアリスの秘密鍵aを取得可能。